package cn.buk.tms.eotms.dao;

import cn.buk.common.util.DateUtil;
import cn.buk.tms.eotms.entity.BillInfo;
import cn.buk.tms.eotms.report.dto.*;
import jakarta.transaction.Transactional;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Component
@Transactional
public class ReportDaoImpl extends AbstractDao implements ReportDao {

  @Override
  public List<ReportFlightTicketDto> searchFlightTickets(int ownerId, int customerId, Date beginDate, Date endDate) {
    return em.createNamedQuery("BillFlightTicket.searchMonthlyTickets", ReportFlightTicketDto.class)
            .setParameter("enterpriseId", ownerId)
            .setParameter("customerId", customerId)
            .setParameter("beginDate", beginDate)
            .setParameter("endDate", endDate)
            .getResultList();
  }

  @Override
  public List<ReportFlightRefundDto> searchFlightRefunds(int ownerId, int customerId, Date beginDate, Date endDate) {
    return em.createNamedQuery("BillFlightRefund.searchMonthly", ReportFlightRefundDto.class)
            .setParameter("enterpriseId", ownerId)
            .setParameter("customerId", customerId)
            .setParameter("beginDate", beginDate)
            .setParameter("endDate", endDate)
            .getResultList();
  }

  @Override
  public List<ReportFlightChangeDto> searchFlightChanges(int ownerId, int customerId, Date beginDate, Date endDate) {
    return  em.createNamedQuery("BillChangeOrder.searchMonthly", ReportFlightChangeDto.class)
            .setParameter("enterpriseId", ownerId)
            .setParameter("customerId", customerId)
            .setParameter("beginDate", beginDate)
            .setParameter("endDate", endDate)
            .getResultList();
  }

  @Override
  public List<ReportVasDto> searchVasOrders(int ownerId, int customerId, Date beginDate, Date endDate) {
    return em.createNamedQuery("BillVasOrder.searchMonthly", ReportVasDto.class)
            .setParameter("enterpriseId", ownerId)
            .setParameter("customerId", customerId)
            .setParameter("beginDate", beginDate)
            .setParameter("endDate", endDate)
            .getResultList();
  }

  @Override
  public List<ReportHotelDto> searchHotelOrders(int ownerId, int customerId, Date beginDate, Date endDate) {
    return em.createNamedQuery("BillHotelBooking.searchMonthly", ReportHotelDto.class)
            .setParameter("enterpriseId", ownerId)
            .setParameter("customerId", customerId)
            .setParameter("beginDate", beginDate)
            .setParameter("endDate", endDate)
            .getResultList();
  }

  @Override
  public List<ReportTrainDto> searchTrainOrders(int ownerId, int customerId, Date beginDate, Date endDate) {
    return em.createNamedQuery("BillTrainTicket.searchMonthly", ReportTrainDto.class)
            .setParameter("enterpriseId", ownerId)
            .setParameter("customerId", customerId)
            .setParameter("beginDate", beginDate)
            .setParameter("endDate", endDate)
            .getResultList();
  }

  @Override
  public List<ReportStatDailyDto> statDaily(int ownerId, int customerId, LocalDate beginDate, LocalDate endDate) {
    List<ReportStatDailyDto> results = new ArrayList<>();

    List<Object[]> stats = em.createQuery("select b.opDate as opDate, " +
            "sum(b.billSum) as totalAmount " +
            "from BillInfo b  " +
            " where b.enterpriseId = :enterpriseId and b.customerId = :customerId and b.opDate >= :beginDate and b.opDate <= :endDate " +
            " group by b.opDate "
            + " order by b.opDate")
            .setParameter("enterpriseId", ownerId)
            .setParameter("customerId", customerId)
            .setParameter("beginDate", DateUtil.createDate(beginDate))
            .setParameter("endDate", DateUtil.createDate(endDate))
            .getResultList();


    for (Object[] stat : stats) {
      ReportStatDailyDto dto = new ReportStatDailyDto();

      dto.setOpDate((Date)stat[0]);
      dto.setTotalAmount((double)stat[1]);

      results.add(dto);
    }

    return results;
  }

  @Override
  public List<ReportStatisticDto> statMonthSaleByAirlines(int ownerId, int customerId, Date beginDate, Date endDate) {
    List<ReportStatisticDto> results = new ArrayList<>();

    List<Object[]> stats = em.createQuery("select b.carrier, count(b) as billCount, " +
            "sum(b.billSum) as totalAmount " +
            "from BillInfo b  " +
            " where b.enterpriseId = :enterpriseId and b.customerId = :customerId and b.opDate >= :beginDate and b.opDate <= :endDate and b.billType = :billType " +
            " group by b.carrier " +
            " order by b.carrier ")
            .setParameter("enterpriseId", ownerId)
            .setParameter("customerId", customerId)
            .setParameter("beginDate", beginDate)
            .setParameter("endDate", endDate)
            .setParameter("billType", BillInfo.BILL_TYPE_FLIGHT)
            .getResultList();


    for (Object[] stat : stats) {
      ReportStatisticDto dto = new ReportStatisticDto();

      dto.setCarrier((String) stat[0]);

      int count = ((Number) stat[1]).intValue();
      dto.setCount(count);

      double amount = ((Number) stat[2]).doubleValue();
      dto.setTotalAmount(amount);

      results.add(dto);
    }

    return results;
  }
}
